import os
import sys
import json
import time
import tkinter as tk
from tkinter import ttk, filedialog, messagebox, scrolledtext
from pathlib import Path
import threading
import numpy as np
from PIL import Image, ImageTk
import matplotlib.pyplot as plt

# 设置matplotlib后端为Agg
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

# 添加项目路径
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
if parent_dir not in sys.path:
    sys.path.append(parent_dir)

# 导入项目模块
from utils.visualization import CircuitVisualizer
from config import get_parse_args

# 设置中文字体
CN_FONT = "Microsoft YaHei UI"

# 主题颜色
THEME_COLOR = {
    'primary': '#2196F3',
    'primary_dark': '#1976D2',
    'primary_light': '#BBDEFB',
    'secondary': '#FF4081',
    'error': '#F44336',
    'warning': '#FFC107',
    'success': '#4CAF50',
    'surface': '#FFFFFF',
    'background': '#F5F5F5',
    'text': '#212121',
    'text_secondary': '#757575',
    'border': '#E0E0E0'
}

class ToolTip:
    """工具提示类"""
    def __init__(self, widget, text):
        self.widget = widget
        self.text = text
        self.tooltip = None
        self.widget.bind("<Enter>", self.show)
        self.widget.bind("<Leave>", self.hide)
    
    def show(self, event=None):
        """显示工具提示"""
        x, y, _, _ = self.widget.bbox("insert")
        x += self.widget.winfo_rootx() + 25
        y += self.widget.winfo_rooty() + 25
        
        # 创建弹出式窗口
        self.tooltip = tk.Toplevel(self.widget)
        self.tooltip.wm_overrideredirect(True)  # 去除标题栏
        self.tooltip.wm_geometry(f"+{x}+{y}")
        
        # 添加文本标签
        label = ttk.Label(self.tooltip, text=self.text, wraplength=250,
                         background="#FFFFE0", relief="solid", borderwidth=1)
        label.pack(padx=2, pady=2)
    
    def hide(self, event=None):
        """隐藏工具提示"""
        if self.tooltip:
            self.tooltip.destroy()
            self.tooltip = None

class SimpleDeepTPIApp:
    """DeepTPI测试点插入系统界面"""
    
    def __init__(self, root):
        """初始化应用程序"""
        self.root = root
        self.root.title("DeepTPI测试点插入系统")
        
        # 设置窗口大小和位置
        window_width = 1200
        window_height = 800
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        center_x = int((screen_width - window_width) / 2)
        center_y = int((screen_height - window_height) / 2)
        self.root.geometry(f"{window_width}x{window_height}+{center_x}+{center_y}")
        
        # 设置应用程序图标（如果有的话）
        try:
            if os.path.exists(os.path.join(parent_dir, "assets", "icon.ico")):
                self.root.iconbitmap(os.path.join(parent_dir, "assets", "icon.ico"))
        except Exception:
            pass
        
        # 初始化变量
        self.init_variables()
        
        # 设置样式
        self.setup_styles()
        
        # 创建UI
        self.create_ui()
        
        # 初始化电路可视化器
        try:
            self.visualizer = CircuitVisualizer()
        except Exception as e:
            self.log_to_console(f"[WARNING] 初始化电路可视化器失败: {str(e)}", "warning")
            self.visualizer = None
        
    def init_variables(self):
        """初始化应用程序变量"""
        # 路径变量
        self.bench_dir = tk.StringVar(value=os.path.join(parent_dir, "run"))
        self.data_dir = tk.StringVar(value=os.path.join(parent_dir, "data", "ITC22_dataset", "test"))
        self.feature_pretrain_model = tk.StringVar(value=os.path.join(parent_dir, "exp", "deepgate", "pretrained.pth"))
        # 移除RL模型变量
        
        # 测试参数变量
        self.target = tk.StringVar(value="LBIST")
        self.dataset = tk.StringVar(value="benchmarks")
        self.gate_types = tk.StringVar(value="INPUT,AND,NOT,BUFF")
        self.num_rounds = tk.StringVar(value="10")
        self.no_cp = tk.StringVar(value="-1")  # -1表示自动计算
        self.no_tp_each_round = tk.StringVar(value="1")
        
        # 电路和结果变量
        self.selected_circuit = tk.StringVar()
        self.circuit_list = []
        self.baseline_tc = tk.StringVar(value="0.00%")
        self.cop_tc = tk.StringVar(value="0.00%")
        self.dg_tc = tk.StringVar(value="0.00%")
        self.improvement = tk.StringVar(value="0.00%")
        
        # 测试运行状态
        self.test_running = False
        self.test_thread = None
        self.results_data = {}
        
        # 状态栏
        self.status_text = tk.StringVar(value="就绪")
    
    def setup_styles(self):
        """设置应用程序样式"""
        self.style = ttk.Style()
        
        # 配置基本样式
        self.style.configure('TFrame', background=THEME_COLOR['surface'])
        self.style.configure('TLabel', background=THEME_COLOR['surface'], foreground=THEME_COLOR['text'], font=(CN_FONT, 10))
        self.style.configure('TButton', font=(CN_FONT, 10), padding=(8, 3))
        self.style.configure('TEntry', font=(CN_FONT, 10), fieldbackground=THEME_COLOR['background'])
        
        # 配置框架样式
        self.style.configure('TLabelframe', background=THEME_COLOR['surface'], bordercolor=THEME_COLOR['border'])
        self.style.configure('TLabelframe.Label', background=THEME_COLOR['surface'], foreground=THEME_COLOR['primary_dark'], font=(CN_FONT, 11, 'bold'))
        
        # 配置可拖动分隔面板样式
        self.style.configure('TPanedwindow', background=THEME_COLOR['border'])
        
        # 配置特殊样式
        self.style.configure('Header.TLabel', font=(CN_FONT, 12, 'bold'), foreground=THEME_COLOR['primary_dark'])
        
        # 配置按钮样式
        self.style.configure('Primary.TButton', 
                             background=THEME_COLOR['primary'], 
                             foreground='black',
                             font=(CN_FONT, 10, 'bold'))
        
        # 配置运行测试按钮样式 - 更加醒目
        self.style.configure('Run.TButton', 
                             background=THEME_COLOR['secondary'], 
                             foreground='black',
                             font=(CN_FONT, 12, 'bold'),
                             padding=(20, 8))
        
        # 配置状态栏样式
        self.style.configure('Status.TLabel', 
                             background=THEME_COLOR['primary_light'], 
                             foreground=THEME_COLOR['text'], 
                             relief="flat", 
                             padding=5)
                             
        # 配置卡片样式
        self.style.configure('Card.TFrame',
                            background=THEME_COLOR['surface'],
                            bordercolor=THEME_COLOR['border'],
                            relief='solid',
                            borderwidth=1)
                             
        # 配置列表框样式
        self.list_style = {
            'font': (CN_FONT, 10), 
            'bg': THEME_COLOR['background'], 
            'selectbackground': THEME_COLOR['primary'], 
            'selectforeground': 'white',
            'borderwidth': 1,
            'relief': 'solid'
        }
        
        # 配置控制台样式                   
        self.console_style = {
            'font': (CN_FONT, 10), 
            'bg': '#282C34', 
            'fg': '#ABB2BF',
            'insertbackground': '#ABB2BF',  # 光标颜色
            'selectbackground': '#3E4451',  # 选中背景色
            'selectforeground': '#FFFFFF',  # 选中文本色
            'relief': 'flat',
            'borderwidth': 0,
            'padx': 10,
            'pady': 10
        }
        
    def create_ui(self):
        """创建改进的用户界面 - 左右分割布局"""
        # 创建主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 创建左右分割的布局 - 使用PanedWindow实现可拖动分隔
        main_paned = ttk.PanedWindow(main_frame, orient=tk.HORIZONTAL)
        main_paned.pack(fill=tk.BOTH, expand=True)
        
        # 左侧面板 - 包含配置和电路列表
        left_frame = ttk.Frame(main_paned)
        main_paned.add(left_frame, weight=30)  # 30%的宽度
        
        # 右侧面板 - 包含结果显示和控制台
        right_frame = ttk.Frame(main_paned)
        main_paned.add(right_frame, weight=70)  # 70%的宽度
        
        # 在右侧创建上下分割的布局
        right_paned = ttk.PanedWindow(right_frame, orient=tk.VERTICAL)
        right_paned.pack(fill=tk.BOTH, expand=True)
        
        # 右上 - 结果显示区域
        result_frame = ttk.LabelFrame(right_paned, text="测试结果")
        right_paned.add(result_frame, weight=30)  # 30%的高度
        
        # 右下 - 控制台输出区域
        console_frame = ttk.LabelFrame(right_paned, text="控制台输出")
        right_paned.add(console_frame, weight=70)  # 70%的高度
        
        # ===== 左侧面板内容 =====
        # 配置区域
        config_frame = ttk.LabelFrame(left_frame, text="基本配置")
        config_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 添加内边距容器
        config_inner = ttk.Frame(config_frame)
        config_inner.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 数据目录
        self.create_path_entry(config_inner, "数据目录:", self.data_dir, "选择测试数据集目录")
        
        # 预训练模型
        self.create_path_entry(config_inner, "预训练模型:", self.feature_pretrain_model, "选择预训练模型文件")
        
        # 添加单电路测试选项
        circuit_frame = ttk.Frame(config_inner)
        circuit_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(circuit_frame, text="测试单电路:", width=10).pack(side=tk.LEFT)
        
        self.circuit_entry = ttk.Entry(circuit_frame)
        self.circuit_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 添加工具提示
        ToolTip(self.circuit_entry, "指定要测试的单个电路名称，留空则测试所有电路")
        
        # 更新配置的回调函数
        def update_circuit_config(*args):
            if not hasattr(self, 'config'):
                self.config = {}
            self.config["circuit"] = self.circuit_entry.get()
        
        # 绑定焦点离开事件来更新配置
        self.circuit_entry.bind("<FocusOut>", update_circuit_config)
        
        # 测试轮次
        self.create_entry(config_inner, "测试轮次:", self.num_rounds)
        
        # 每轮测试点数量
        self.create_entry(config_inner, "每轮测试点:", self.no_tp_each_round)
        
        # 控制按钮区域
        control_frame = ttk.Frame(config_inner)
        control_frame.pack(fill=tk.X, pady=15)
        
        scan_btn = ttk.Button(control_frame, text="扫描电路", command=self.scan_circuits, 
                             style="Primary.TButton")
        scan_btn.pack(side=tk.LEFT, padx=5)
        
        load_default_btn = ttk.Button(control_frame, text="默认配置", command=self.load_default_config)
        load_default_btn.pack(side=tk.LEFT, padx=5)
        
        # 电路列表区域
        circuit_list_frame = ttk.LabelFrame(left_frame, text="电路列表")
        circuit_list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建列表和滚动条
        list_container = ttk.Frame(circuit_list_frame)
        list_container.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        scrollbar = ttk.Scrollbar(list_container)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.circuit_listbox = tk.Listbox(list_container, yscrollcommand=scrollbar.set, 
                                         **self.list_style)
        self.circuit_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        scrollbar.config(command=self.circuit_listbox.yview)
        
        # 绑定选择事件
        self.circuit_listbox.bind('<<ListboxSelect>>', self.on_circuit_select)
        
        # 操作按钮
        btn_frame = ttk.Frame(circuit_list_frame)
        btn_frame.pack(fill=tk.X, padx=10, pady=10)
        
        run_btn = ttk.Button(btn_frame, text="运行测试", 
                           command=self.run_test_on_selected, 
                           style="Run.TButton")
        run_btn.pack(side=tk.LEFT, padx=5)
        
        view_btn = ttk.Button(btn_frame, text="查看电路", command=self.view_selected_circuit,
                            style="Primary.TButton")
        view_btn.pack(side=tk.LEFT, padx=5)
        
        # ===== 右侧面板内容 =====
        # 结果显示区域
        result_inner = ttk.Frame(result_frame)
        result_inner.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 显示当前选中的电路
        circuit_name_frame = ttk.Frame(result_inner)
        circuit_name_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(circuit_name_frame, text="当前电路:", font=(CN_FONT, 10, 'bold')).pack(side=tk.LEFT)
        ttk.Label(circuit_name_frame, textvariable=self.selected_circuit,
                font=(CN_FONT, 10, 'bold'), foreground=THEME_COLOR['primary_dark']).pack(side=tk.LEFT, padx=5)
        
        # 测试覆盖率结果 - 使用更现代的卡片式布局
        result_cards_frame = ttk.Frame(result_inner)
        result_cards_frame.pack(fill=tk.X, padx=5, pady=10)
        
        # 创建结果卡片
        self.create_result_card(result_cards_frame, "基线测试覆盖率", self.baseline_tc, 0, 0)
        self.create_result_card(result_cards_frame, "COP测试覆盖率", self.cop_tc, 0, 1)
        self.create_result_card(result_cards_frame, "DeepTPI测试覆盖率", self.dg_tc, 1, 0)
        self.create_result_card(result_cards_frame, "改进幅度", self.improvement, 1, 1)
        
        # 报告和导出按钮
        report_frame = ttk.Frame(result_inner)
        report_frame.pack(fill=tk.X, padx=5, pady=10)
        
        gen_report_btn = ttk.Button(report_frame, text="生成报告", 
                                  command=self.generate_html_report,
                                  style="Primary.TButton")
        gen_report_btn.pack(side=tk.LEFT, padx=5)
        
        view_report_btn = ttk.Button(report_frame, text="查看报告", 
                                   command=self.view_latest_report)
        view_report_btn.pack(side=tk.LEFT, padx=5)
        
        export_btn = ttk.Button(report_frame, text="导出结果", 
                              command=self.export_results)
        export_btn.pack(side=tk.LEFT, padx=5)
        
        # 控制台输出区域
        console_inner = ttk.Frame(console_frame)
        console_inner.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 控制台工具栏
        console_toolbar = ttk.Frame(console_inner)
        console_toolbar.pack(fill=tk.X, pady=5)
        
        clear_console_btn = ttk.Button(console_toolbar, text="清除控制台", 
                                     command=self.clear_console)
        clear_console_btn.pack(side=tk.LEFT, padx=2)
        
        save_log_btn = ttk.Button(console_toolbar, text="保存日志", 
                                command=self.save_console_log)
        save_log_btn.pack(side=tk.LEFT, padx=2)
        
        # 创建控制台文本区域 - 占据大部分空间
        console_container = ttk.Frame(console_inner)
        console_container.pack(fill=tk.BOTH, expand=True, pady=5)
        
        self.console_text = scrolledtext.ScrolledText(console_container, 
                                                    **self.console_style)
        self.console_text.pack(fill=tk.BOTH, expand=True)
        self.console_text.config(state=tk.DISABLED)
        
        # 配置tags用于着色
        self.console_text.tag_configure("info", foreground='#ABB2BF')
        self.console_text.tag_configure("error", foreground=THEME_COLOR['error'])
        self.console_text.tag_configure("success", foreground=THEME_COLOR['success'])
        self.console_text.tag_configure("warning", foreground=THEME_COLOR['warning'])
        
        # 创建状态栏
        status_bar = ttk.Label(self.root, textvariable=self.status_text, style='Status.TLabel')
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 初始化日志
        self.log_to_console("系统启动完成，请扫描电路或加载默认配置后开始测试", "info")
        
    def create_result_card(self, parent, title, variable, row, col):
        """创建结果卡片"""
        card = ttk.Frame(parent, style='Card.TFrame')
        card.grid(row=row, column=col, padx=10, pady=5, sticky="nsew")
        
        # 标题
        title_label = ttk.Label(card, text=title, 
                 font=(CN_FONT, 10), 
                 foreground=THEME_COLOR['text_secondary'])
        title_label.pack(padx=10, pady=(10, 5))
        
        # 值
        value_label = ttk.Label(card, textvariable=variable, 
                 font=(CN_FONT, 16, 'bold'), 
                 foreground=THEME_COLOR['primary_dark'])
        value_label.pack(padx=10, pady=(0, 10))
        
        # 根据参数名称设置不同的样式
        if "改进" in title:
            value_label.configure(foreground=THEME_COLOR['success'])
        elif "DeepTPI" in title:
            value_label.configure(foreground=THEME_COLOR['secondary'])
        
        # 配置网格权重
        parent.grid_columnconfigure(0, weight=1)
        parent.grid_columnconfigure(1, weight=1)
        parent.grid_rowconfigure(0, weight=1)
        parent.grid_rowconfigure(1, weight=1)
        
        return card

    def create_path_entry(self, parent, label_text, variable, help_text=""):
        """创建带浏览按钮的路径输入框"""
        frame = ttk.Frame(parent)
        frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(frame, text=label_text, width=10).pack(side=tk.LEFT)
        
        # 存储实际StringVar变量的引用
        varstr = variable
        
        # 创建文本框
        entry = ttk.Entry(frame, textvariable=varstr)
        entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        
        # 记录到config_entries字典中
        if not hasattr(self, 'config_entries'):
            self.config_entries = {}
        # 使用变量名或标签文本作为键，而不是StringVar对象本身
        key = label_text
        self.config_entries[key] = entry
        
        # 为不同类型的路径创建不同的浏览函数
        if "预训练模型" in label_text:
            browse_command = lambda: self.browse_model_file(varstr)
        else:
            browse_command = lambda: self.browse_directory(varstr)
        
        # 创建浏览按钮
        browse_btn = ttk.Button(frame, text="浏览", command=browse_command)
        browse_btn.pack(side=tk.RIGHT, padx=5)
        
        # 添加工具提示
        if help_text:
            tooltip = ToolTip(entry, help_text)
        
        return entry
        
    def browse_model_file(self, var_ref=None):
        """浏览并选择模型文件"""
        # 获取初始目录
        initial_dir = os.getcwd()
        if var_ref and var_ref.get() and os.path.exists(os.path.dirname(var_ref.get())):
            initial_dir = os.path.dirname(var_ref.get())
        elif hasattr(self, 'data_dir') and self.data_dir.get() and os.path.exists(self.data_dir.get()):
            initial_dir = self.data_dir.get()
            
        # 明确定义文件类型
        filetypes = [
            ("PyTorch模型", "*.pth"),
            ("所有文件", "*.*")
        ]
        
        # 打开文件选择对话框
        filepath = filedialog.askopenfilename(
            initialdir=initial_dir,
            title="选择模型文件",
            filetypes=filetypes
        )
        
        if filepath:
            # 设置模型路径
            var_ref.set(filepath)
            
            # 更新配置
            if not hasattr(self, 'config'):
                self.config = {}
                
            # 设置为预训练模型
            self.config["feature_pretrain_model"] = filepath
            
            # 日志记录
            self.log_to_console(f"已选择预训练模型: {filepath}", "info")
            self.status_text.set(f"已加载预训练模型: {os.path.basename(filepath)}")

    def browse_directory(self, var_ref=None):
        """浏览并选择目录"""
        # 获取初始目录
        initial_dir = os.getcwd()
        if var_ref and var_ref.get():
            initial_dir = var_ref.get()
            
        # 选择目录对话框
        dir_path = filedialog.askdirectory(
            title="选择目录",
            initialdir=initial_dir
        )
        
        if dir_path:
            if var_ref:
                var_ref.set(dir_path)
                self.log_to_console(f"已选择目录: {dir_path}", "info")
            else:
                # 如果没有指定引用，则设置数据目录
                self.data_dir.set(dir_path)
                self.log_to_console(f"已选择数据目录: {dir_path}", "info")

    def create_entry(self, parent, label_text, variable):
        """创建标准输入框"""
        frame = ttk.Frame(parent)
        frame.pack(fill=tk.X, padx=5, pady=2)
        
        ttk.Label(frame, text=label_text, width=10).pack(side=tk.LEFT)
        
        entry = ttk.Entry(frame, textvariable=variable)
        entry.pack(side=tk.LEFT, fill=tk.X, expand=True)

    def scan_circuits(self):
        """扫描可用电路"""
        self.log_to_console("正在扫描电路...", "info")
        self.status_text.set("正在扫描电路...")
        
        try:
            # 检查数据目录是否存在
            data_dir = self.data_dir.get()
            if not os.path.exists(data_dir):
                raise FileNotFoundError(f"数据目录不存在: {data_dir}")
                
            # 从数据集文件中获取电路列表
            circuit_list = []
            
            # 尝试加载benchmark电路
            # 搜索各种可能的circuit文件名
            circuit_files = []
            for file in os.listdir(data_dir):
                if file.endswith('.npz') and ('circuit' in file.lower() or 'benchmark' in file.lower()):
                    circuit_files.append(os.path.join(data_dir, file))
            
            # 如果找到了circuit文件，尝试加载
            for circuit_file in circuit_files:
                try:
                    # 加载电路数据
                    self.log_to_console(f"尝试加载电路文件: {os.path.basename(circuit_file)}", "info")
                    data = np.load(circuit_file, allow_pickle=True)
                    
                    # 尝试不同的键名方式读取电路名称
                    if 'names' in data:
                        names = list(data['names'])
                        circuit_list.extend(names)
                        self.log_to_console(f"从'names'键找到{len(names)}个电路", "info")
                    elif 'circuits' in data:
                        circuits = data['circuits'].item()
                        names = list(circuits.keys())
                        circuit_list.extend(names)
                        self.log_to_console(f"从'circuits'键找到{len(names)}个电路", "info")
                    else:
                        # 尝试从keys中提取名称
                        keys = list(data.keys())
                        circuit_names = [k for k in keys if k not in ['names', 'arr_0', 'circuits']]
                        if circuit_names:
                            circuit_list.extend(circuit_names)
                            self.log_to_console(f"从数据键中找到{len(circuit_names)}个电路", "info")
                except Exception as e:
                    self.log_to_console(f"加载电路文件 {os.path.basename(circuit_file)} 失败: {str(e)}", "error")
            
            # 如果没有从npz文件找到电路，检查目录结构
            if not circuit_list:
                for root, dirs, files in os.walk(data_dir):
                    for dir_name in dirs:
                        # 跳过隐藏目录
                        if dir_name.startswith('.'):
                            continue
                        # 检查是否是电路目录
                        if os.path.exists(os.path.join(root, dir_name, "data.pt")):
                            circuit_list.append(dir_name)
                
                if circuit_list:
                    self.log_to_console(f"从目录结构中找到{len(circuit_list)}个电路", "info")
            
            # 如果仍然没有找到电路，检查bench目录
            if not circuit_list:
                bench_dir = self.bench_dir.get()
                if os.path.exists(bench_dir):
                    for file in os.listdir(bench_dir):
                        if file.endswith(".bench"):
                            circuit_name = os.path.splitext(file)[0]
                            circuit_list.append(circuit_name)
                    
                    if circuit_list:
                        self.log_to_console(f"从bench目录中找到{len(circuit_list)}个电路", "info")
            
            # 如果还是没找到，检查visualization目录中的bench文件
            if not circuit_list:
                bench_dir = self.bench_dir.get()
                vis_dir = os.path.join(bench_dir, "visualization")
                if os.path.exists(vis_dir):
                    for file in os.listdir(vis_dir):
                        if file.endswith(".bench"):
                            circuit_name = os.path.splitext(file)[0]
                            circuit_list.append(circuit_name)
                    
                    if circuit_list:
                        self.log_to_console(f"从visualization目录中找到{len(circuit_list)}个电路", "info")
            
            # 更新电路列表
            if circuit_list:
                self.circuit_list = circuit_list
                self.update_circuit_list()
                self.log_to_console(f"扫描完成，找到 {len(self.circuit_list)} 个电路", "success")
            else:
                # 如果仍找不到电路，使用示例数据
                self.circuit_list = ["b04_C_000", "b04_C_003", "b07_C_000", "b15_C_001"]
                self.update_circuit_list()
                self.log_to_console(f"未找到真实电路，已加载示例电路数据", "warning")
        
        except Exception as e:
            self.log_to_console(f"扫描电路出错: {str(e)}", "error")
            # 使用示例数据
            self.circuit_list = ["b04_C_000", "b04_C_003", "b07_C_000", "b15_C_001"]
            self.update_circuit_list()
        
        self.status_text.set("就绪")

    def update_circuit_list(self):
        """更新电路列表显示"""
        self.circuit_listbox.delete(0, tk.END)
        for circuit in self.circuit_list:
            self.circuit_listbox.insert(tk.END, circuit)

    def on_circuit_select(self, event):
        """处理电路选择事件"""
        selection = self.circuit_listbox.curselection()
        if selection:
            index = selection[0]
            circuit = self.circuit_list[index]
            self.selected_circuit.set(circuit)
            self.log_to_console(f"选择电路: {circuit}", "info")
            
            # 更新config中的circuit参数
            if not hasattr(self, 'config'):
                self.config = {}
            self.config["circuit"] = circuit
            
            # 如果有circuit_entry，也更新它
            if hasattr(self, 'circuit_entry'):
                self.circuit_entry.delete(0, tk.END)
                self.circuit_entry.insert(0, circuit)
            
            # 尝试读取已存在的测试结果
            try:
                result_file = os.path.join(self.bench_dir.get(), "results", f"{circuit}_results.json")
                if os.path.exists(result_file):
                    with open(result_file, 'r', encoding='utf-8') as f:
                        results = json.load(f)
                        self.baseline_tc.set(results.get('baseline_tc', "0.00%"))
                        self.cop_tc.set(results.get('cop_tc', "0.00%"))
                        self.dg_tc.set(results.get('dg_tc', "0.00%"))
                        self.improvement.set(results.get('improvement', "0.00%"))
                        self.log_to_console(f"已加载电路 {circuit} 的测试结果", "info")
                        return
            except Exception as e:
                self.log_to_console(f"读取测试结果失败: {str(e)}", "warning")
            
            # 如果没有找到结果，显示默认值
            self.baseline_tc.set("0.00%")
            self.cop_tc.set("0.00%")
            self.dg_tc.set("0.00%")
            self.improvement.set("0.00%")

    def view_selected_circuit(self):
        """查看选中的电路"""
        if not self.selected_circuit.get():
            messagebox.showinfo("提示", "请先选择一个电路")
            return
        
        circuit_name = self.selected_circuit.get()
        self.log_to_console(f"正在加载电路图: {circuit_name}", "info")
        self.status_text.set(f"正在加载电路图: {circuit_name}")
        
        try:
            # 首先检查benchmarks目录中的bench文件
            bench_dir = os.path.join("run", "benchmarks")
            bench_file = os.path.join(bench_dir, f"{circuit_name}.bench")
            
            # 如果bench文件不存在，尝试在visualization目录查找
            if not os.path.exists(bench_file):
                vis_dir = os.path.join(bench_dir, "visualization")
                if os.path.exists(vis_dir):
                    bench_file = os.path.join(vis_dir, f"{circuit_name}.bench")
            
            # 如果仍找不到，尝试从数据目录生成电路文件
            if not os.path.exists(bench_file):
                # 显示提示
                self.log_to_console(f"找不到电路文件: {bench_file}", "warning")
                self.log_to_console("尝试从数据目录生成电路文件...", "info")
                
                # 尝试从数据目录生成电路文件
                try:
                    # 搜索可能的电路文件
                    circuit_files = []
                    for file in os.listdir(self.data_dir.get()):
                        if file.endswith('.npz') and ('circuit' in file.lower() or 'benchmark' in file.lower()):
                            circuit_files.append(os.path.join(self.data_dir.get(), file))
                    
                    # 尝试从每个文件中加载电路
                    circuit_data = None
                    for circuit_file in circuit_files:
                        try:
                            data = np.load(circuit_file, allow_pickle=True)
                            if 'circuits' in data:
                                circuits = data['circuits'].item()
                                if circuit_name in circuits:
                                    circuit_data = circuits[circuit_name]
                                    break
                        except Exception as e:
                            self.log_to_console(f"[WARNING] 加载电路文件失败: {str(e)}", "warning")
                    
                    if circuit_data is not None:
                        # 确保visualization目录存在
                        vis_dir = os.path.join(bench_dir, "visualization")
                        if not os.path.exists(vis_dir):
                            os.makedirs(vis_dir)
                        
                        # 转换为bench格式并保存
                        bench_file = os.path.join(vis_dir, f"{circuit_name}.bench")
                        from utils.circuit_utils import convert_circuit_to_bench
                        if convert_circuit_to_bench(circuit_data, bench_file):
                            self.log_to_console(f"已生成电路文件: {bench_file}", "success")
                        else:
                            raise Exception("转换电路文件失败")
                    else:
                        # 如果找不到电路数据，创建示例电路
                        vis_dir = os.path.join(bench_dir, "visualization")
                        if not os.path.exists(vis_dir):
                            os.makedirs(vis_dir)
                        
                        bench_file = os.path.join(vis_dir, f"{circuit_name}.bench")
                        with open(bench_file, 'w') as f:
                            f.write(f"# 示例电路: {circuit_name}\n")
                            f.write("INPUT(a)\n")
                            f.write("INPUT(b)\n")
                            f.write("OUTPUT(o)\n")
                            f.write("gate1 = AND(a, b)\n")
                            f.write("o = NOT(gate1)\n")
                        
                        self.log_to_console(f"已创建示例电路文件: {bench_file}", "success")
                except Exception as e:
                    messagebox.showerror("错误", f"无法创建电路文件: {str(e)}")
                    self.log_to_console(f"创建电路文件失败: {str(e)}", "error")
                    self.status_text.set("就绪")
                    return
            
            # 创建一个新窗口显示电路
            circuit_window = tk.Toplevel(self.root)
            circuit_window.title(f"电路 - {circuit_name}")
            circuit_window.geometry("800x600")
            
            # 添加状态标签
            status_label = ttk.Label(circuit_window, text="正在渲染电路图...", foreground=THEME_COLOR['primary'])
            status_label.pack(pady=10)
            
            # 使用线程渲染电路图避免阻塞UI
            def render_circuit():
                try:
                    # 确保图像目录存在
                    images_dir = os.path.join(bench_dir, "images")
                    if not os.path.exists(images_dir):
                        os.makedirs(images_dir)
                    
                    # 设置输出图像路径
                    img_path = os.path.join(images_dir, f"{circuit_name}.png")
                    
                    # 在这里调用可视化函数
                    if self.visualizer:
                        self.visualizer.set_bench_dir(os.path.dirname(bench_file))
                        
                        # 设置matplotlib后端为Agg
                        matplotlib.use('Agg')
                        
                        # 如果可视化器有visualize_circuit方法，直接调用
                        if hasattr(self.visualizer, 'visualize_circuit') and callable(getattr(self.visualizer, 'visualize_circuit')):
                            try:
                                # 清除当前图形
                                plt.clf()
                                
                                img_data = self.visualizer.visualize_circuit(os.path.basename(bench_file), output_type='data')
                                with open(img_path, 'wb') as f:
                                    f.write(img_data)
                                
                                # 等待文件写入完成
                                time.sleep(0.5)
                                
                                # 验证图像文件
                                if not os.path.exists(img_path) or os.path.getsize(img_path) == 0:
                                    raise Exception("生成的图像文件无效")
                                
                            except Exception as e:
                                self.log_to_console(f"[WARNING] visualize_circuit失败: {str(e)}", "warning")
                                # 使用备选方案
                                from utils.visualization import draw_circuit
                                
                                # 清除当前图形
                                plt.clf()
                                
                                # 绘制电路
                                draw_circuit(os.path.abspath(bench_file), os.path.abspath(img_path), show=False)
                                
                                # 确保图像被保存并关闭
                                plt.savefig(os.path.abspath(img_path), format='png', bbox_inches='tight', dpi=300)
                                plt.close()
                        else:
                            # 否则使用draw_circuit方法
                            from utils.visualization import draw_circuit
                            
                            # 清除当前图形
                            plt.clf()
                            
                            # 绘制电路
                            draw_circuit(os.path.abspath(bench_file), os.path.abspath(img_path), show=False)
                            
                            # 确保图像被保存并关闭
                            plt.savefig(os.path.abspath(img_path), format='png', bbox_inches='tight', dpi=300)
                            plt.close()
                    else:
                        # 如果visualizer不可用，使用基本的draw_circuit方法
                        from utils.visualization import draw_circuit
                        
                        # 清除当前图形
                        plt.clf()
                        
                        # 绘制电路
                        draw_circuit(os.path.abspath(bench_file), os.path.abspath(img_path), show=False)
                        
                        # 确保图像被保存并关闭
                        plt.savefig(os.path.abspath(img_path), format='png', bbox_inches='tight', dpi=300)
                        plt.close()
                    
                    # 等待文件写入完成
                    time.sleep(0.5)
                    
                    # 验证图像文件
                    if not os.path.exists(img_path) or os.path.getsize(img_path) == 0:
                        raise Exception("生成的图像文件无效")
                    
                    # 加载和显示图像
                    img = Image.open(img_path)
                    
                    # 调整图像大小以适应窗口
                    window_width = circuit_window.winfo_width() - 20
                    window_height = circuit_window.winfo_height() - 40
                    
                    img_width, img_height = img.size
                    scale = min(window_width/img_width, window_height/img_height)
                    
                    if scale < 1:  # 只有当图像太大时才缩小
                        new_width = int(img_width * scale)
                        new_height = int(img_height * scale)
                        img = img.resize((new_width, new_height), Image.LANCZOS)
                    
                    # 将图像转换为Tkinter PhotoImage
                    tk_img = ImageTk.PhotoImage(img)
                    
                    # 在UI线程中更新界面
                    def update_ui():
                        status_label.destroy()  # 移除状态标签
                        
                        # 创建带滚动条的画布
                        canvas_frame = ttk.Frame(circuit_window)
                        canvas_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
                        
                        h_scrollbar = ttk.Scrollbar(canvas_frame, orient=tk.HORIZONTAL)
                        v_scrollbar = ttk.Scrollbar(canvas_frame, orient=tk.VERTICAL)
                        
                        canvas = tk.Canvas(canvas_frame, 
                                          xscrollcommand=h_scrollbar.set,
                                          yscrollcommand=v_scrollbar.set)
                        
                        h_scrollbar.config(command=canvas.xview)
                        v_scrollbar.config(command=canvas.yview)
                        
                        h_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
                        v_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
                        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
                        
                        # 添加图像到画布
                        img_label = ttk.Label(canvas, image=tk_img)
                        img_label.image = tk_img  # 保持引用防止被垃圾回收
                        
                        canvas.create_window(0, 0, anchor=tk.NW, window=img_label)
                        canvas.config(scrollregion=canvas.bbox(tk.ALL))
                        
                        # 添加保存按钮
                        save_btn = ttk.Button(circuit_window, text="保存图像", 
                                            command=lambda: self.save_circuit_image(img, circuit_name))
                        save_btn.pack(pady=5)
                        
                        self.log_to_console(f"已加载电路图: {circuit_name}", "success")
                        self.status_text.set("就绪")
                    
                    circuit_window.after(0, update_ui)
                    
                except Exception as e:
                    def show_error():
                        messagebox.showerror("错误", f"加载电路图失败: {str(e)}")
                        self.log_to_console(f"加载电路图失败: {str(e)}", "error")
                        circuit_window.destroy()
                        self.status_text.set("就绪")
                    
                    circuit_window.after(0, show_error)
            
            # 启动渲染线程
            threading.Thread(target=render_circuit, daemon=True).start()
            
        except Exception as e:
            messagebox.showerror("错误", f"查看电路失败: {str(e)}")
            self.log_to_console(f"查看电路失败: {str(e)}", "error")
            self.status_text.set("就绪")
    
    def save_circuit_image(self, img, circuit_name):
        """保存电路图像"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG图像", "*.png"), ("JPEG图像", "*.jpg"), ("所有文件", "*.*")],
            initialfile=f"{circuit_name}_circuit.png"
        )
        
        if file_path:
            try:
                img.save(file_path)
                self.log_to_console(f"已保存电路图像到: {file_path}", "success")
            except Exception as e:
                messagebox.showerror("错误", f"保存图像失败: {str(e)}")
                self.log_to_console(f"保存图像失败: {str(e)}", "error")

    def run_test_on_selected(self):
        """运行测试在选定的电路上"""
        # 检查是否选择了电路
        if not self.selected_circuit.get():
            self.log_to_console("请先选择一个电路进行测试", "warning")
            return
        
        # 检查数据目录是否存在
        if not self.data_dir.get() or not os.path.isdir(self.data_dir.get()):
            self.log_to_console("请先选择数据目录", "warning")
            return
            
        # 构建确认消息
        msg = f"确认开始测试?\n"
        msg += f"电路: {self.selected_circuit.get()}\n"
        msg += f"数据目录: {self.data_dir.get()}\n"
        
        # 显示模型信息
        if self.feature_pretrain_model.get():
            msg += f"特征预训练模型: {self.feature_pretrain_model.get()}\n"
        else:
            msg += "未选择特征预训练模型\n"
        
        # 确认对话框
        if not messagebox.askyesno("确认", msg):
            return
        
        # 准备参数
        base_args = [
            "--data_dir", self.data_dir.get(),
            "--circuit", self.selected_circuit.get()
        ]
        
        # 添加可选模型参数
        if self.feature_pretrain_model.get():
            base_args.extend(["--pretrain_model", self.feature_pretrain_model.get()])
        
        # 确保基准目录存在
        bench_dir = os.path.join("run", "benchmarks")
        if not os.path.exists(bench_dir):
            os.makedirs(bench_dir)
            
        # 在线程中运行测试
        def run_test():
            try:
                self.log_to_console("[INFO] 开始测试电路...")
                self.log_to_console(f"[INFO] 参数: {' '.join(base_args)}")
                
                # 导入测试函数
                import sys
                import os
                
                # 添加src目录到Python路径
                src_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
                if src_dir not in sys.path:
                    sys.path.append(src_dir)
                
                from test_specific_circuit import test_specific_circuit
                from config import get_parse_args
                from utils.circuit_utils import convert_circuit_to_bench
                
                # 解析参数
                args = get_parse_args()
                
                # 更新参数
                for i in range(0, len(base_args), 2):
                    key = base_args[i].lstrip('-')
                    value = base_args[i + 1]
                    setattr(args, key, value)
                
                # 运行测试前，尝试生成bench文件
                circuit_name = self.selected_circuit.get()
                bench_file = os.path.join(bench_dir, f"{circuit_name}.bench")
                
                if not os.path.exists(bench_file):
                    try:
                        # 尝试从数据目录中找到电路数据并转换为bench格式
                        self.log_to_console(f"[INFO] 正在生成bench文件: {bench_file}")
                        
                        # 搜索可能的电路文件
                        circuit_files = []
                        for file in os.listdir(self.data_dir.get()):
                            if file.endswith('.npz') and ('circuit' in file.lower() or 'benchmark' in file.lower()):
                                circuit_files.append(os.path.join(self.data_dir.get(), file))
                        
                        # 尝试从每个文件中加载电路
                        circuit_data = None
                        for circuit_file in circuit_files:
                            try:
                                data = np.load(circuit_file, allow_pickle=True)
                                if 'circuits' in data:
                                    circuits = data['circuits'].item()
                                    if circuit_name in circuits:
                                        circuit_data = circuits[circuit_name]
                                        break
                            except Exception as e:
                                self.log_to_console(f"[WARNING] 加载电路文件失败: {str(e)}", "warning")
                        
                        if circuit_data is not None:
                            # 转换为bench格式并保存
                            convert_circuit_to_bench(circuit_data, bench_file)
                            self.log_to_console(f"[INFO] 已生成bench文件: {bench_file}")
                        else:
                            self.log_to_console(f"[WARNING] 未找到电路数据，无法生成bench文件", "warning")
                    except Exception as e:
                        self.log_to_console(f"[WARNING] 生成bench文件失败: {str(e)}", "warning")
                
                # 运行测试
                self.log_to_console(f"[INFO] 正在测试电路: {circuit_name}")
                results = test_specific_circuit(args)
                
                if not results:
                    self.log_to_console("[WARNING] 测试未返回结果", "warning")
                    return
                
                # 添加电路名称到结果中
                if isinstance(results, dict):
                    results['circuit_name'] = circuit_name
                
                # 检查是否找到了近似匹配电路
                if results.get('matched_circuit'):
                    self.log_to_console(f"[INFO] 使用了近似匹配电路: {results.get('matched_circuit')}", "info")
                
                # 生成电路图像
                try:
                    # 保存图像的目录
                    images_dir = os.path.join(bench_dir, 'images')
                    if not os.path.exists(images_dir):
                        os.makedirs(images_dir)
                        
                    # 生成和保存图像
                    circuit_name = results.get('matched_circuit', self.selected_circuit.get())
                    # 确保文件名小写，避免matplotlib格式识别问题
                    image_path = os.path.join(images_dir, f"{circuit_name.lower()}.png")
                    
                    # 如果bench文件存在，生成图像
                    if os.path.exists(bench_file):
                        try:
                            from utils.visualization import generate_circuit_image
                            # 确保输出目录存在
                            os.makedirs(os.path.dirname(image_path), exist_ok=True)
                            # 使用绝对路径
                            abs_bench_file = os.path.abspath(bench_file)
                            abs_image_path = os.path.abspath(image_path)
                            
                            # 设置matplotlib后端为Agg
                            import matplotlib
                            matplotlib.use('Agg')
                            
                            # 生成图像数据
                            image_data = generate_circuit_image(abs_bench_file)
                            
                            # 手动将图像数据保存为文件
                            with open(abs_image_path, 'wb') as img_file:
                                img_file.write(image_data)
                            
                            # 验证文件是否成功保存
                            if os.path.exists(abs_image_path):
                                file_size = os.path.getsize(abs_image_path)
                                if file_size < 1000:  # 文件太小可能有问题
                                    self.log_to_console(f"[WARNING] 生成的图片文件可能有问题（文件太小: {file_size}字节）", "warning")
                                    raise Exception("生成的图片文件太小")
                                
                                results['circuit_image_path'] = image_path
                                self.log_to_console(f"[INFO] 已生成电路图像: {image_path}", "info")
                            else:
                                raise Exception("生成的图片文件不存在")
                            
                        except Exception as e:
                            self.log_to_console(f"[WARNING] 使用generate_circuit_image失败: {str(e)}", "warning")
                            # 尝试使用draw_circuit作为备选方案
                            try:
                                from utils.visualization import draw_circuit
                                import matplotlib
                                matplotlib.use('Agg')
                                
                                # 清除当前图形
                                import matplotlib.pyplot as plt
                                plt.close('all')
                                
                                # 确保路径使用小写扩展名
                                output_path = abs_image_path.lower()
                                if not output_path.endswith('.png'):
                                    output_path = os.path.splitext(output_path)[0] + '.png'
                                
                                # 绘制电路
                                success = draw_circuit(abs_bench_file, output_path, show=False)
                                
                                if not success:
                                    raise Exception("draw_circuit返回了失败状态")
                                
                                # 验证文件是否成功保存
                                if os.path.exists(output_path):
                                    file_size = os.path.getsize(output_path)
                                    if file_size < 1000:  # 文件太小可能有问题
                                        self.log_to_console(f"[WARNING] 生成的图片文件可能有问题（文件太小: {file_size}字节）", "warning")
                                        raise Exception("生成的图片文件太小")
                                    
                                    results['circuit_image_path'] = output_path
                                    self.log_to_console(f"[INFO] 已使用备选方案生成电路图像: {output_path}", "info")
                                else:
                                    raise Exception("备选方案生成的图片文件不存在")
                                
                            except Exception as e2:
                                self.log_to_console(f"[WARNING] 备选方案也失败: {str(e2)}", "warning")
                    else:
                        self.log_to_console(f"[WARNING] 找不到bench文件，无法生成图像", "warning")
                except Exception as e:
                    self.log_to_console(f"[WARNING] 生成电路图像失败: {str(e)}", "warning")
                
                # 保存结果到文件
                self.save_result_to_file(results)
                
                # 更新UI
                self.update_ui(results)
                
            except Exception as e:
                self.log_to_console(f"[ERROR] 测试过程中发生错误: {str(e)}", "error")
                import traceback
                self.log_to_console(traceback.format_exc(), "error")
                
        # 在新线程中运行测试，避免阻塞UI
        test_thread = threading.Thread(target=run_test)
        test_thread.daemon = True
        test_thread.start()
        
        self.log_to_console(f"[INFO] 已启动测试线程...", "info")

    def load_default_config(self):
        """加载默认配置"""
        self.log_to_console("正在加载默认配置...", "info")
        
        # 设置默认配置值
        self.bench_dir.set(os.path.join(parent_dir, "run"))
        self.data_dir.set(os.path.join(parent_dir, "data", "ITC22_dataset", "test"))
        self.feature_pretrain_model.set(os.path.join(parent_dir, "exp", "deepgate", "pretrained.pth"))
        self.target.set("LBIST")
        self.dataset.set("benchmarks")
        self.gate_types.set("INPUT,AND,NOT,BUFF")
        self.num_rounds.set("10")
        self.no_cp.set("-1")
        self.no_tp_each_round.set("1")
        
        self.log_to_console("已加载默认配置", "success")

    def clear_console(self):
        """清除控制台输出"""
        self.console_text.config(state=tk.NORMAL)
        self.console_text.delete(1.0, tk.END)
        self.console_text.config(state=tk.DISABLED)

    def save_console_log(self):
        """保存控制台日志"""
        if not self.console_text.get(1.0, tk.END).strip():
            messagebox.showinfo("提示", "控制台中没有内容可保存")
            return
            
        file_path = filedialog.asksaveasfilename(
            defaultextension=".log",
            filetypes=[("日志文件", "*.log"), ("文本文件", "*.txt"), ("所有文件", "*.*")],
            initialfile="deeptpi_console.log"
        )
        
        if file_path:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(self.console_text.get(1.0, tk.END))
            self.log_to_console(f"日志已保存到 {file_path}", "success")

    def log_to_console(self, message, level="info"):
        """向控制台添加日志"""
        if self.console_text:
            self.console_text.config(state=tk.NORMAL)
            timestamp = time.strftime("%H:%M:%S", time.localtime())
            self.console_text.insert(tk.END, f"[{timestamp}] {message}\n", level)
            self.console_text.see(tk.END)
            self.console_text.config(state=tk.DISABLED)

    def generate_html_report(self):
        """生成HTML测试报告"""
        if not self.selected_circuit.get():
            messagebox.showinfo("提示", "请先选择一个电路")
            return
            
        self.log_to_console("正在生成HTML报告...", "info")
        self.status_text.set("正在生成HTML报告...")
        
        try:
            circuit_name = self.selected_circuit.get()
            bench_dir = self.bench_dir.get()
            
            # 创建visualization目录
            report_dir = os.path.join(bench_dir, "visualization")
            if not os.path.exists(report_dir):
                os.makedirs(report_dir)
            
            # 获取测试结果
            results_dir = os.path.join(bench_dir, "results")
            result_file = os.path.join(results_dir, f"{circuit_name}_results.json")
            
            circuit_results = {}
            if os.path.exists(result_file):
                with open(result_file, 'r', encoding='utf-8') as f:
                    circuit_results = json.load(f)
            else:
                # 使用当前显示的结果
                circuit_results = {
                    "circuit": circuit_name,
                    "baseline_tc": self.baseline_tc.get(),
                    "cop_tc": self.cop_tc.get(),
                    "dg_tc": self.dg_tc.get(),
                    "improvement": self.improvement.get(),
                    "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
                }
            
            # 准备电路图像
            bench_file = os.path.join(bench_dir, f"{circuit_name}.bench")
            cop_bench_file = os.path.join(bench_dir, f"{circuit_name}_cop.bench")
            dg_bench_file = os.path.join(bench_dir, f"{circuit_name}_dg.bench")
            
            image_paths = {}
            
            # 生成基础电路图像
            if os.path.exists(bench_file):
                try:
                    # 在单独的线程中生成图像，避免阻塞UI
                    def generate_images():
                        try:
                            # 使用可视化器生成图像
                            self.visualizer.set_bench_dir(bench_dir)
                            baseline_img_path = os.path.join(report_dir, f"{circuit_name}_baseline.png")
                            
                            # 尝试使用不同的可视化方法
                            try:
                                if hasattr(self.visualizer, 'visualize_circuit') and callable(getattr(self.visualizer, 'visualize_circuit')):
                                    img_data = self.visualizer.visualize_circuit(os.path.basename(bench_file), output_type='image')
                                    # 如果返回的是图像数据而不是路径，保存为图像文件
                                    if isinstance(img_data, bytes):
                                        with open(baseline_img_path, 'wb') as f:
                                            f.write(img_data)
                                else:
                                    from utils.visualization import draw_circuit
                                    draw_circuit(bench_file, baseline_img_path, show=False)
                                
                                image_paths['baseline'] = baseline_img_path
                                self.log_to_console(f"已生成基线电路图像", "success")
                            except Exception as e:
                                self.log_to_console(f"生成基线电路图像失败: {str(e)}", "error")
                            
                            # 生成COP电路图像
                            if os.path.exists(cop_bench_file):
                                try:
                                    cop_img_path = os.path.join(report_dir, f"{circuit_name}_cop.png")
                                    from utils.visualization import draw_circuit
                                    draw_circuit(cop_bench_file, cop_img_path, show=False)
                                    image_paths['cop'] = cop_img_path
                                    self.log_to_console(f"已生成COP电路图像", "success")
                                except Exception as e:
                                    self.log_to_console(f"生成COP电路图像失败: {str(e)}", "error")
                            
                            # 生成DeepTPI电路图像
                            if os.path.exists(dg_bench_file):
                                try:
                                    dg_img_path = os.path.join(report_dir, f"{circuit_name}_dg.png")
                                    from utils.visualization import draw_circuit
                                    draw_circuit(dg_bench_file, dg_img_path, show=False)
                                    image_paths['dg'] = dg_img_path
                                    self.log_to_console(f"已生成DeepTPI电路图像", "success")
                                except Exception as e:
                                    self.log_to_console(f"生成DeepTPI电路图像失败: {str(e)}", "error")
                            
                            # 生成比较图像
                            if os.path.exists(bench_file) and os.path.exists(dg_bench_file):
                                try:
                                    compare_img_path = os.path.join(report_dir, f"{circuit_name}_compare.png")
                                    from utils.visualization import compare_circuits
                                    compare_circuits(bench_file, dg_bench_file, compare_img_path, 
                                                  title=f"Circuit {circuit_name}: Baseline vs DeepTPI")
                                    image_paths['compare'] = compare_img_path
                                    self.log_to_console(f"已生成比较电路图像", "success")
                                except Exception as e:
                                    self.log_to_console(f"生成比较电路图像失败: {str(e)}", "error")
                            
                            # 生成HTML报告
                            self.generate_actual_report(circuit_name, circuit_results, image_paths, report_dir)
                            
                        except Exception as e:
                            self.log_to_console(f"生成图像失败: {str(e)}", "error")
                            # 继续生成没有图像的报告
                            self.generate_actual_report(circuit_name, circuit_results, {}, report_dir)
                    
                    # 启动图像生成线程
                    threading.Thread(target=generate_images, daemon=True).start()
                    
                except Exception as e:
                    self.log_to_console(f"启动图像生成线程失败: {str(e)}", "error")
                    # 生成没有图像的报告
                    self.generate_actual_report(circuit_name, circuit_results, {}, report_dir)
            else:
                # 如果没有bench文件，生成没有图像的报告
                self.log_to_console(f"找不到电路文件: {bench_file}", "warning")
                self.generate_actual_report(circuit_name, circuit_results, {}, report_dir)
            
        except Exception as e:
            messagebox.showerror("错误", f"生成报告失败: {str(e)}")
            self.log_to_console(f"生成报告失败: {str(e)}", "error")
            self.status_text.set("就绪")
    
    def generate_actual_report(self, circuit_name, results, image_paths, report_dir):
        """生成实际的HTML报告"""
        try:
            report_path = os.path.join(report_dir, "visualization_report.html")
            
            # 创建HTML内容
            html_content = f"""
            <!DOCTYPE html>
            <html>
            <head>
                <title>DeepTPI测试报告 - {circuit_name}</title>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width, initial-scale=1">
                <style>
                    body {{ font-family: Arial, sans-serif; margin: 20px; line-height: 1.6; color: #333; }}
                    h1, h2, h3 {{ color: #1a73e8; }}
                    .container {{ max-width: 1200px; margin: 0 auto; }}
                    .header {{ text-align: center; margin-bottom: 30px; background-color: #e8f0fe; padding: 20px; border-radius: 5px; }}
                    .result-card {{ background-color: #fff; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); 
                                   padding: 20px; margin-bottom: 30px; }}
                    .metrics {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; margin: 20px 0; }}
                    .metric {{ background-color: #f5f5f5; padding: 15px; border-radius: 5px; text-align: center; }}
                    .metric .value {{ font-size: 24px; font-weight: bold; color: #1a73e8; margin-bottom: 5px; }}
                    .metric .label {{ font-size: 14px; color: #5f6368; }}
                    .improvement {{ background-color: #e6f4ea; }}
                    .images {{ display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 20px; }}
                    .image-container {{ text-align: center; }}
                    .image-container img {{ max-width: 100%; height: auto; border: 1px solid #ddd; }}
                    .image-container .caption {{ margin-top: 10px; font-size: 14px; color: #5f6368; }}
                    .footer {{ text-align: center; margin-top: 30px; padding: 20px; font-size: 12px; color: #5f6368; }}
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="header">
                        <h1>DeepTPI测试报告</h1>
                        <p>电路: <strong>{circuit_name}</strong> | 生成时间: {time.strftime("%Y-%m-%d %H:%M:%S")}</p>
                    </div>
                    
                    <div class="result-card">
                        <h2>测试结果摘要</h2>
                        <div class="metrics">
                            <div class="metric">
                                <div class="value">{results.get('baseline_tc', '0.00%')}</div>
                                <div class="label">基线测试覆盖率</div>
                            </div>
                            <div class="metric">
                                <div class="value">{results.get('cop_tc', '0.00%')}</div>
                                <div class="label">COP测试覆盖率</div>
                            </div>
                            <div class="metric">
                                <div class="value">{results.get('dg_tc', '0.00%')}</div>
                                <div class="label">DeepTPI测试覆盖率</div>
                            </div>
                            <div class="metric improvement">
                                <div class="value">{results.get('improvement', '0.00%')}</div>
                                <div class="label">相比基线的改进幅度</div>
                            </div>
                        </div>
                    </div>
            """
            
            # 添加图像区域
            if image_paths:
                html_content += """
                    <div class="result-card">
                        <h2>电路可视化</h2>
                """
                
                # 电路图像
                if any(k in image_paths for k in ['baseline', 'cop', 'dg']):
                    html_content += """
                        <h3>电路图</h3>
                        <div class="images">
                    """
                    
                    # 基线电路
                    if 'baseline' in image_paths:
                        html_content += f"""
                            <div class="image-container">
                                <img src="{os.path.basename(image_paths['baseline'])}" alt="基线电路">
                                <div class="caption">基线电路 (覆盖率: {results.get('baseline_tc', '0.00%')})</div>
                            </div>
                        """
                    
                    # COP电路
                    if 'cop' in image_paths:
                        html_content += f"""
                            <div class="image-container">
                                <img src="{os.path.basename(image_paths['cop'])}" alt="COP电路">
                                <div class="caption">COP电路 (覆盖率: {results.get('cop_tc', '0.00%')})</div>
                            </div>
                        """
                    
                    # DeepTPI电路
                    if 'dg' in image_paths:
                        html_content += f"""
                            <div class="image-container">
                                <img src="{os.path.basename(image_paths['dg'])}" alt="DeepTPI电路">
                                <div class="caption">DeepTPI电路 (覆盖率: {results.get('dg_tc', '0.00%')})</div>
                            </div>
                        """
                    
                    html_content += """
                        </div>
                    """
                
                # 比较图像
                if 'compare' in image_paths:
                    html_content += f"""
                        <h3>对比图</h3>
                        <div class="images">
                            <div class="image-container">
                                <img src="{os.path.basename(image_paths['compare'])}" alt="电路对比">
                                <div class="caption">基线 vs DeepTPI 对比</div>
                            </div>
                        </div>
                    """
                
                html_content += """
                    </div>
                """
            else:
                html_content += """
                    <div class="result-card">
                        <h2>电路可视化</h2>
                        <p>未生成电路图像或生成过程中出现错误。</p>
                    </div>
                """
            
            # 添加测试参数
            html_content += f"""
                <div class="result-card">
                    <h2>测试参数</h2>
                    <ul>
                        <li><strong>数据目录:</strong> {self.data_dir.get()}</li>
                        <li><strong>预训练模型:</strong> {os.path.basename(self.feature_pretrain_model.get())}</li>
                        <li><strong>测试轮次:</strong> {self.num_rounds.get()}</li>
                        <li><strong>每轮测试点:</strong> {self.no_tp_each_round.get()}</li>
                        <li><strong>目标类型:</strong> {self.target.get()}</li>
                        <li><strong>数据集:</strong> {self.dataset.get()}</li>
                        <li><strong>门类型:</strong> {self.gate_types.get()}</li>
                    </ul>
                </div>
                
                <div class="footer">
                    由DeepTPI测试点插入系统生成 | &copy; {time.strftime("%Y")}
                </div>
            </div>
            </body>
            </html>
            """
            
            # 写入HTML文件
            with open(report_path, 'w', encoding='utf-8') as f:
                f.write(html_content)
            
            # 更新UI
            def update_ui():
                self.log_to_console(f"报告已生成: {report_path}", "success")
                self.status_text.set("就绪")
                messagebox.showinfo("成功", "HTML报告已生成，可以点击'查看报告'按钮查看")
            
            self.root.after(0, update_ui)
            
        except Exception as e:
            def show_error():
                messagebox.showerror("错误", f"生成HTML报告失败: {str(e)}")
                self.log_to_console(f"生成HTML报告失败: {str(e)}", "error")
                self.status_text.set("就绪")
            
            self.root.after(0, show_error)

    def view_latest_report(self):
        """查看最新的HTML报告"""
        report_path = os.path.join(self.bench_dir.get(), "visualization", "visualization_report.html")
        
        if os.path.exists(report_path):
            self.log_to_console(f"正在打开报告: {report_path}", "info")
            try:
                # 使用默认浏览器打开报告
                webbrowser.open(f"file://{os.path.abspath(report_path)}")
            except Exception as e:
                messagebox.showerror("错误", f"打开报告失败: {str(e)}")
                self.log_to_console(f"打开报告失败: {str(e)}", "error")
        else:
            # 如果报告不存在，提示生成报告
            if messagebox.askyesno("提示", "报告文件不存在，是否现在生成报告？"):
                self.generate_html_report()

    def export_results(self):
        """导出测试结果"""
        if not self.selected_circuit.get():
            messagebox.showinfo("提示", "请先选择一个电路")
            return
            
        file_path = filedialog.asksaveasfilename(
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")],
            initialfile=f"{self.selected_circuit.get()}_results.json"
        )
        
        if file_path:
            # 示例结果数据
            result_data = {
                "circuit": self.selected_circuit.get(),
                "baseline_tc": self.baseline_tc.get(),
                "cop_tc": self.cop_tc.get(),
                "dg_tc": self.dg_tc.get(),
                "improvement": self.improvement.get(),
                "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }
            
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(result_data, f, indent=2, ensure_ascii=False)
                
            self.log_to_console(f"结果已导出到 {file_path}", "success")

    def update_ui(self, result):
        """更新UI显示的测试结果"""
        try:
            # 更新测试覆盖率
            if isinstance(result, dict):
                # 基准测试覆盖率
                if 'baseline_tc' in result:
                    baseline_tc = float(result['baseline_tc'])
                    self.baseline_tc.set(f"{baseline_tc:.2f}%")
                
                # COP测试覆盖率
                if 'cop_tc' in result:
                    cop_tc = float(result['cop_tc'])
                    self.cop_tc.set(f"{cop_tc:.2f}%")
                
                # DeepTPI测试覆盖率
                if 'dg_tc' in result:
                    dg_tc = float(result['dg_tc'])
                    self.dg_tc.set(f"{dg_tc:.2f}%")
                    
                    # 计算改进幅度
                    if 'baseline_tc' in result:
                        improvement = dg_tc - baseline_tc
                        self.improvement.set(f"{improvement:.2f}%")
                
                # 如果有电路图像，显示它
                if 'circuit_image_path' in result and os.path.exists(result['circuit_image_path']):
                    self.display_image(result['circuit_image_path'])
            
            # 更新状态栏
            self.status_text.set("测试完成")
            
        except Exception as e:
            self.log_to_console(f"[ERROR] 更新UI时发生错误: {str(e)}", "error")
            import traceback
            self.log_to_console(traceback.format_exc(), "error")
    
    def save_result_to_file(self, result):
        """保存测试结果到文件"""
        try:
            # 确保结果目录存在
            bench_dir = os.path.join('run', 'benchmarks')
            results_dir = os.path.join(bench_dir, 'results')
            if not os.path.exists(results_dir):
                os.makedirs(results_dir)
            
            # 获取电路名称
            circuit_name = result.get('circuit_name', self.selected_circuit)
            
            # 准备结果数据
            result_data = {
                "circuit": circuit_name,
                "baseline_tc": f"{result.get('baseline_tc', 0):.2f}%",
                "cop_tc": f"{result.get('cop_tc', 0):.2f}%",
                "dg_tc": f"{result.get('dg_tc', 0):.2f}%",
                "improvement": f"{result.get('dg_tc', 0) - result.get('baseline_tc', 0):.2f}%",
                "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
            }
            
            # 如果使用了近似匹配，添加相关信息
            if result.get('matched_circuit') and result.get('matched_circuit') != circuit_name:
                result_data["matched_circuit"] = result.get('matched_circuit')
            
            # 保存为JSON文件
            result_file = os.path.join(results_dir, f"{circuit_name}_results.json")
            with open(result_file, 'w', encoding='utf-8') as f:
                json.dump(result_data, f, indent=2, ensure_ascii=False)
                
            self.log_to_console(f"[INFO] 测试结果已保存到: {result_file}")
        except Exception as e:
            self.log_to_console(f"[ERROR] 保存结果时发生错误: {str(e)}")
    
    def display_image(self, image_path):
        """显示电路图像"""
        try:
            if hasattr(self, 'circuit_image_label'):
                # 加载图像
                from PIL import Image, ImageTk
                
                # 打开图像
                image = Image.open(image_path)
                
                # 调整图像大小以适应UI
                max_width = 800
                max_height = 600
                width, height = image.size
                
                # 计算缩放比例
                ratio = min(max_width / width, max_height / height)
                new_width = int(width * ratio)
                new_height = int(height * ratio)
                
                # 调整图像大小
                image = image.resize((new_width, new_height), Image.LANCZOS)
                
                # 转换为Tkinter可用的格式
                photo = ImageTk.PhotoImage(image)
                
                # 更新图像标签
                self.circuit_image_label.config(image=photo)
                self.circuit_image_label.image = photo  # 保持引用
                
                self.log_to_console(f"[INFO] 已显示电路图像: {image_path}")
        except Exception as e:
            self.log_to_console(f"[ERROR] 显示图像时发生错误: {str(e)}")

    def show_error(self, error_msg):
        """显示错误消息"""
        try:
            messagebox.showerror("错误", str(error_msg))
        except Exception as e:
            print(f"显示错误消息失败: {str(e)}")
        
    def show_circuit_image(self):
        """显示电路图"""
        try:
            if not self.selected_circuit.get():
                self.show_error("请先选择一个电路")
                return
                
            bench_file = os.path.join("run", "benchmarks", f"{self.selected_circuit.get()}.bench")
            if not os.path.exists(bench_file):
                self.show_error(f"找不到电路文件: {bench_file}")
                return
                
            # 创建images目录（如果不存在）
            images_dir = os.path.join("run", "benchmarks", "images")
            os.makedirs(images_dir, exist_ok=True)
            
            # 生成输出文件路径（确保是小写，扩展名为.png）
            circuit_name = self.selected_circuit.get().lower()
            output_file = os.path.join(images_dir, f"{circuit_name}.png")
            
            self.log_to_console(f"[DEBUG] 正在生成电路图...")
            self.log_to_console(f"[DEBUG] 输入文件: {bench_file}")
            self.log_to_console(f"[DEBUG] 输出文件: {output_file}")
            
            # 设置matplotlib后端
            import matplotlib
            matplotlib.use('Agg')
            
            try:
                # 首先尝试使用draw_circuit
                from utils.visualization import draw_circuit
                # 确保绝对路径
                abs_bench_file = os.path.abspath(bench_file)
                abs_output_file = os.path.abspath(output_file)
                
                # 确保输出目录存在
                os.makedirs(os.path.dirname(abs_output_file), exist_ok=True)
                
                success = draw_circuit(abs_bench_file, abs_output_file, show=False)
                
                if not success or not os.path.exists(abs_output_file):
                    raise Exception("生成电路图失败")
                    
            except Exception as draw_error:
                self.log_to_console(f"[WARNING] 使用draw_circuit失败: {str(draw_error)}", "warning")
                try:
                    # 尝试使用generate_circuit_image作为备选方案
                    from utils.visualization import generate_circuit_image
                    
                    # 确保绝对路径
                    abs_bench_file = os.path.abspath(bench_file)
                    abs_output_file = os.path.abspath(output_file)
                    
                    # 生成图像数据
                    image_data = generate_circuit_image(abs_bench_file)
                    
                    # 手动将图像数据保存为文件
                    with open(abs_output_file, 'wb') as img_file:
                        img_file.write(image_data)
                    
                    if not os.path.exists(abs_output_file):
                        raise Exception("生成的图像文件不存在")
                    
                    # 验证文件大小
                    file_size = os.path.getsize(abs_output_file)
                    if file_size < 1000:
                        self.log_to_console(f"[WARNING] 生成的图像文件可能有问题（文件大小: {file_size}字节）", "warning")
                    
                    self.log_to_console(f"[INFO] 已使用备选方案生成电路图像: {output_file}", "info")
                    
                except Exception as gen_error:
                    self.log_to_console(f"[WARNING] 备选方案也失败: {str(gen_error)}", "warning")
                    raise Exception(f"无法生成电路图: {str(gen_error)}")
            
            # 创建新窗口显示图片
            image_window = tk.Toplevel(self.root)
            image_window.title(f"电路 - {self.selected_circuit.get()}")
            
            # 使用PIL加载图片
            from PIL import Image, ImageTk
            image = Image.open(abs_output_file)
            
            # 获取屏幕尺寸
            screen_width = image_window.winfo_screenwidth()
            screen_height = image_window.winfo_screenheight()
            
            # 计算合适的显示尺寸
            display_width = min(image.width, screen_width * 0.8)
            display_height = min(image.height, screen_height * 0.8)
            
            # 等比例缩放
            ratio = min(display_width / image.width, display_height / image.height)
            new_width = int(image.width * ratio)
            new_height = int(image.height * ratio)
            
            # 调整图片大小
            image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
            photo = ImageTk.PhotoImage(image)
            
            # 创建带滚动条的画布
            canvas = tk.Canvas(image_window)
            scrollbar_y = tk.Scrollbar(image_window, orient="vertical", command=canvas.yview)
            scrollbar_x = tk.Scrollbar(image_window, orient="horizontal", command=canvas.xview)
            
            # 配置画布
            canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
            
            # 放置组件
            scrollbar_y.pack(side="right", fill="y")
            scrollbar_x.pack(side="bottom", fill="x")
            canvas.pack(side="left", fill="both", expand=True)
            
            # 创建框架来容纳图片
            frame = tk.Frame(canvas)
            canvas.create_window((0, 0), window=frame, anchor="nw")
            
            # 显示图片
            label = tk.Label(frame, image=photo)
            label.image = photo  # 保持引用
            label.pack()
            
            # 更新画布的滚动区域
            frame.update_idletasks()
            canvas.config(scrollregion=canvas.bbox("all"))
            
            # 添加保存按钮
            def save_image():
                file_path = filedialog.asksaveasfilename(
                    defaultextension=".png",
                    filetypes=[("PNG files", "*.png"), ("All files", "*.*")],
                    initialfile=f"{self.selected_circuit.get()}.png"
                )
                if file_path:
                    image.save(file_path)
                    messagebox.showinfo("成功", "图片已保存")
            
            save_button = tk.Button(image_window, text="保存图像", command=save_image)
            save_button.pack(side="bottom", pady=5)
            
        except Exception as e:
            error_msg = f"加载电路图失败: {str(e)}"
            self.log_to_console(f"[ERROR] {error_msg}", "error")
            self.show_error(error_msg)

# 主程序入口
if __name__ == "__main__":
    # 创建Tkinter根窗口
    root = tk.Tk()
    
    # 创建应用程序实例
    app = SimpleDeepTPIApp(root)
    
    # 启动应用程序主循环
    root.mainloop() 